home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / System / WackyPointer INIT / WackyPInit.p < prev    next >
Encoding:
Text File  |  1994-11-20  |  7.3 KB  |  274 lines  |  [TEXT/PJMM]

  1. unit WackyPointerInit;
  2. {  Written by Brian Stern July 1993, updated Nov., 1994 }
  3. {  Copyright 1993 Aster Software Inc. }
  4. {  All rights reserved. }
  5. {  The WackyPointer Init is a silly little thing written as }
  6. {  an exercise in Init writing and to learn how to use the }
  7. {  jGNEFilter and VBLTasks.  When installed on a machine }
  8. {  any mousedown causes the curser to spin around.  It stops }
  9. {  on mouseup (usually). }
  10.  
  11. interface
  12.  
  13.     uses
  14.         Retrace, SysEQu;
  15.  
  16.     procedure main;
  17.  
  18. implementation
  19.  
  20.     const
  21.         ToolScratch = $9CE;
  22.         acurID = 4444;
  23.         kDesiredCount = 3;
  24.  
  25.     type
  26.         pToPtr = ^Ptr;
  27.         pToProcPtr = ^ProcPtr;
  28.         EventPtr = ^EventRecord;
  29.         CursHand = ^CursPtr;
  30.  
  31.         eachCursor = record
  32.                 case integer of
  33.                     1: (
  34.                             cursNum: integer;
  35.                             Spare: integer;
  36.                     );
  37.                     2: (
  38.                             theCurHand: CursHand;
  39.                     );
  40.             end;
  41.  
  42.         acur = record
  43.                 numFrames: integer;
  44.                 FrameCounter: integer;
  45.                 ID: array[0..20] of eachCursor;
  46.             end;
  47.         acurPtr = ^acur;
  48.         acurHand = ^acurPtr;
  49.  
  50.         TaskBlock = record
  51.                 theRecord: VBLTask;
  52.                 theacurHand: acurHand;
  53.                 Installed: Boolean;
  54.             end;
  55.         TBPtr = ^TaskBlock;
  56.  
  57.         IntPtr = ^integer;
  58.         LongIntPtr = ^Longint;
  59.  
  60.         Mess = record           {allow access to single bytes in event message}
  61.                 case Integer of
  62.                     1: (
  63.                             themsg: longint
  64.                     );
  65.                     2: (
  66.                             mess1, mess2: SignedByte;
  67.                             mess3: Integer
  68.                     );
  69.             end;     {Mess}
  70.         PToMess = ^Mess;
  71.  
  72.     var
  73.         gOldGNEFilter: ProcPtr;
  74.         gTaskBlockPtr: TBPtr;
  75.         gCurHand: acurHand;
  76.         gError: OSErr;
  77.  
  78. {*****InstallVBLTask************************************************}
  79.  
  80.     procedure InstallVBLTask;
  81. {  This proc sets a few fields in the VBLTask rec and installs it.}
  82. {  Some apps mask out mouse ups or for some reason they are lost}
  83. {  So always check if the task is already installed before installing it.}
  84. {  It crashes if installed twice.}
  85.     begin
  86.         if gTaskBlockPtr^.Installed = False then
  87.             begin
  88.                 with gTaskBlockPtr^, theRecord do
  89.                     begin
  90.                         vblCount := kDesiredCount;
  91.                         vblPhase := 0;
  92.                         if noErr = VInstall(QElemPtr(gTaskBlockPtr)) then
  93.                             Installed := True;
  94.                     end;
  95.             end;
  96.     end;
  97.  
  98. {*****RemoveVBLTask************************************************}
  99.  
  100.     procedure RemoveVBLTask;
  101. {Remove the VBLTask from the queue}
  102.     begin
  103.         if gTaskBlockPtr^.Installed = True then
  104.             begin
  105.                 if noErr = VRemove(QElemPtr(gTaskBlockPtr)) then
  106.                     gTaskBlockPtr^.Installed := False;
  107.             end;
  108.     end;
  109.  
  110. {*****GetVBLPtr************************************************}
  111.  
  112.     function GetVBLPtr: TBPtr;
  113. {Courtesy of Grobbins}
  114.     inline
  115.         $2E88;    {Move.L A0, (A7)   Put A0 on the stack}
  116.  
  117.  
  118. {*****TheTask************************************************}
  119.  
  120.     procedure TheTask;
  121. {  This is the VBLTask.  It simply spins the cursor and resets itself}
  122.         var
  123.             TaskBlockPtr: TBPtr;
  124.  
  125.     begin
  126.         TaskBlockPtr := GetVBLPtr;
  127.         with TaskBlockPtr^, theacurHand^^ do
  128.             begin
  129.                 if IntPtr(CrsrBusy)^ = 0 then
  130.                     begin
  131.                         frameCounter := (frameCounter + 1) mod numFrames;
  132.                         SetCursor(ID[frameCounter].theCurHand^^);    {Spin the cursor}
  133.                     end;
  134.                 TaskBlockPtr^.theRecord.vblCount := kDesiredCount;        {Reset the vbltask counter}
  135.             end;
  136.     end;
  137.  
  138. {*****SetUpVBLTask************************************************}
  139.  
  140.     function SetUpVBLTask: integer;
  141. {This function allocates space for a VBLTask record and fills}
  142. {in the fields but it doesn't install it.  The record is }
  143. {installed and removed from the jGNEFilter}
  144.     begin
  145.         gTaskBlockPtr := TBPtr(NewPtrSys(Sizeof(TaskBlock)));    {Allocate space in sys Heap}
  146.         if gTaskBlockPtr <> nil then
  147.             with gTaskBlockPtr^, theRecord do        {Fill in the fields in the record}
  148.                 begin
  149.                     qType := ord(vType);
  150.                     vblAddr := @TheTask;
  151.                     vblCount := kDesiredCount;
  152.                     vblPhase := 0;
  153.                     theacurHand := gCurHand;
  154.                     Installed := False;
  155.                     SetUpVBLTask := NoErr;
  156.                 end
  157.         else
  158.             SetUpVBLTask := -1;        {An error occurred}
  159.     end;
  160.  
  161. {*****UnlinkAndJumpToOldFilter************************************************}
  162.  
  163.     procedure UnlinkAndJumpToOldFilter (theFilterProc: ProcPtr);
  164. {Move the procptr to the stack and JMP to it }
  165.     inline
  166.         $205F,                {MoveA.L  (A7)+, A0 }
  167.         $4CDF, $0C80,         {MoveM.L (A7)+, D7/A2/A3}
  168.         $4E5E,                {Unlk  A6}
  169.         $4ED0;                {JMP(A0)}
  170.  
  171. {*****GetD0************************************************}
  172.  
  173.     function GetD0: longint;
  174.     inline
  175.         $2E80;        {Move.L  D0, (A7)}
  176.  
  177. {*****SetD0************************************************}
  178.  
  179.     procedure SetD0 (theValue: longint);
  180.     inline
  181.         $201F;        {Move.L    ( A7 )+, D0}
  182.  
  183. {*****GetEventPtr************************************************}
  184.  
  185.     function GetEventPtr: EventPtr;
  186.     inline
  187.         $2E89;        {Move.L   A1, (A7)}
  188.  
  189. {*****FilterProc************************************************}
  190.  
  191.     procedure FilterProc;
  192. {This is the jGNEFilter.  It simply checks for mousdowns}
  193. {and mouseups and installs or removes the vbltask.}
  194. {When switching from one app to another there doesn't}
  195. {seem to be a mouseup event to match the mousedown.}
  196. {We could use the process manager to keep track of the current}
  197. {process and then Remove the VBL task if the process changed.}
  198.         var
  199.             theEvent: EventPtr;
  200.             oldProc: ProcPtr;
  201.             saveD0: longint;
  202.     begin
  203.         SetUpA4;                        {Restore A4 to allow access to globals}
  204.         saveD0 := GetD0;            {Save the contents of D0, the function result}
  205.         theEvent := GetEventPtr;    {Get ptr to eventrecord from A1}
  206.         if theEvent^.what = MouseDown then
  207.             InstallVBLTask                {Install VBLTask if mousedown}
  208.         else if theEvent^.what = MouseUp then
  209.             RemoveVBLTask;            {Remove the VBLTask if a mouseup}
  210.         oldProc := gOldGNEFilter;    {Save the address of the previous jGNEFilter in a local variable}
  211.         SetD0(saveD0);                {Restore the contents of D0}
  212.         RestoreA4;
  213.         UnlinkAndJumpToOldFilter(oldProc);        {Execute the previous jGNEFilter}
  214.     end;
  215.  
  216. {*****InstallFilter************************************************}
  217.  
  218.     procedure InstallFilter;
  219. {Save the ProcPtr to the previous jGNEFilter and insert ours}
  220.     begin
  221.         gOldGNEFilter := pToProcPtr(jGNEFilter)^;                                    {Save old Filter proc ptr}
  222.         pToProcPtr(jGNEFilter)^ := ProcPtr(StripAddress(@FilterProc));        {Install new filter proc}
  223.     end;
  224.  
  225. {*****GetTheResources************************************************}
  226.  
  227.     function GetTheResources: Integer;
  228. {Read in the acur resource and the CURS resources}
  229. {All must be marked sysheap and locked}
  230.         var
  231.             tempHand: Handle;
  232.             i: integer;
  233.     begin
  234.         gCurHand := acurHand(GetResource('acur', acurID));            {Read the acur resource}
  235.         if gCurHand = nil then
  236.             begin
  237.                 GetTheResources := -1;
  238.                 Exit(GetTheResources);
  239.             end;
  240.         DetachResource(Handle(gCurHand));
  241.         with gCurHand^^ do
  242.             for i := 0 to numFrames - 1 do
  243.                 begin
  244.                     tempHand := GetResource('CURS', ID[i].cursNum);        {Read in the Cursors}
  245.                     if tempHand = nil then
  246.                         begin
  247.                             GetTheResources := -1;
  248.                             Exit(GetTheResources);
  249.                         end;
  250.                     DetachResource(tempHand);
  251.                     Handle(ID[i]) := tempHand;
  252.                 end;
  253.         gCurHand^^.frameCounter := 0;
  254.         GetTheResources := NoErr;
  255.     end;
  256.  
  257. {*****Main****************************************************}
  258.  
  259.     procedure Main;
  260.         var
  261.             MyHandle: Handle;
  262.     begin
  263.         RememberA4;        {Allows use of globals in the init}
  264.         SetUpA4;
  265.         InstallFilter;            {Install the jGNEFilter}
  266.         if (GetTheResources = NoErr) & (SetUpVBLTask = NoErr) then
  267.             begin            {Only get to here if no errors in getting resources and setting up VBLTask}
  268.                 MyHandle := RecoverHandle(pToPtr(ToolScratch)^);{Pascal puts the address of the init in ToolScratch}
  269.                 DetachResource(MyHandle);        {Detach the resource to remain in memory}
  270.             end;
  271.         RestoreA4;
  272.     end;
  273.  
  274. end.